import os
import tkinter as tk
from tkinter import filedialog, scrolledtext, messagebox, simpledialog
import subprocess
import yt_dlp
from threading import Thread
from process.douyin import handle_aweme_download

class VideoDownloaderApp:
    def __init__(self, root):
        self.root = root
        self.root.title("全平台无水印下载")
        self.root.geometry("900x700")

        # 主框架和滚动条
        main_frame = tk.Frame(root)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        canvas = tk.Canvas(main_frame)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = tk.Scrollbar(main_frame, orient=tk.VERTICAL, command=canvas.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        canvas.configure(yscrollcommand=scrollbar.set)
        canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
        
        inner_frame = tk.Frame(canvas)
        canvas.create_window((0, 0), window=inner_frame, anchor="nw")
        
        # 输入框和按钮
        input_frame = tk.Frame(inner_frame)
        input_frame.pack(pady=10)
        
        self.url_entry = tk.Entry(input_frame, width=60)
        self.url_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Button(input_frame, text="添加", command=self.add_url).pack(side=tk.LEFT, padx=5)
        tk.Button(input_frame, text="清空", command=self.clear_input).pack(side=tk.LEFT, padx=5)
        
        # 链接列表
        list_frame = tk.Frame(inner_frame)
        list_frame.pack(pady=10)
        
        self.url_listbox = tk.Listbox(list_frame, width=80, height=15)
        self.url_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        list_scrollbar = tk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.url_listbox.yview)
        list_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.url_listbox.config(yscrollcommand=list_scrollbar.set)
        
        # 链接操作按钮
        operation_frame = tk.Frame(inner_frame)
        operation_frame.pack(pady=5)
        
        tk.Button(operation_frame, text="修改", command=self.modify_url).pack(side=tk.LEFT, padx=5)
        tk.Button(operation_frame, text="保存", command=self.save_url).pack(side=tk.LEFT, padx=5)
        tk.Button(operation_frame, text="删除", command=self.delete_url).pack(side=tk.LEFT, padx=5)
        
        # 批量操作按钮
        batch_frame = tk.Frame(inner_frame)
        batch_frame.pack(pady=5)
        
        tk.Button(batch_frame, text="全部保存", command=self.save_all_urls).pack(side=tk.LEFT, padx=5)
        self.start_button = tk.Button(batch_frame, text="开始下载", command=self.toggle_download)
        self.start_button.pack(side=tk.LEFT, padx=5)
        tk.Button(batch_frame, text="全部不保存", command=self.unsave_all_urls).pack(side=tk.LEFT, padx=5)
        
        # 打开文件夹按钮
        tk.Button(inner_frame, text="打开下载文件夹", command=self.open_download_folder).pack(pady=5)
        
        # 终端输出
        terminal_frame = tk.Frame(inner_frame)
        terminal_frame.pack(pady=10)
        
        self.terminal = scrolledtext.ScrolledText(terminal_frame, width=100, height=15)
        self.terminal.pack(fill=tk.BOTH, expand=True)
        self.terminal.configure(state='disabled')
        
        # 导入TXT按钮
        tk.Button(inner_frame, text="导入TXT", command=self.import_txt).pack(pady=10)
        
        
        
        # 初始化状态
        self.is_running = False
        self.load_urls()
        
        # 窗口关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)

    def add_url(self):
        """添加网址到列表和文件"""
        url = self.url_entry.get().strip()
        if not url:
            return
            
        self.log(f"已添加链接: {url}")
        self.url_listbox.insert(tk.END, url)
        self.save_urls()
        self.url_entry.delete(0, tk.END)

    def clear_input(self):
        """清空输入框"""
        self.url_entry.delete(0, tk.END)

    def modify_url(self):
        """修改选中的网址"""
        if not self.url_listbox.curselection():
            return
            
        index = self.url_listbox.curselection()[0]
        old_url = self.url_listbox.get(index)
        new_url = simpledialog.askstring("修改链接", "输入新链接:", initialvalue=old_url)
        
        if new_url:
            self.url_listbox.delete(index)
            self.url_listbox.insert(index, new_url)
            self.save_urls()
            self.log(f"已修改链接: {old_url} -> {new_url}")

    def save_url(self):
        """保存选中的网址（添加空格◈◈）"""
        if not self.url_listbox.curselection():
            return
            
        index = self.url_listbox.curselection()[0]
        url = self.url_listbox.get(index)
        
        if " ◈◈" in url:
            new_url = url.replace(" ◈◈", "")
            self.log(f"已取消保存: {url}")
        else:
            new_url = url + " ◈◈"
            self.log(f"已保存链接: {new_url}")
            
        self.url_listbox.delete(index)
        self.url_listbox.insert(index, new_url)
        self.save_urls()

    def delete_url(self):
        """删除选中的网址"""
        if not self.url_listbox.curselection():
            return
            
        index = self.url_listbox.curselection()[0]
        url = self.url_listbox.get(index)
        self.url_listbox.delete(index)
        self.save_urls()
        self.log(f"已删除链接: {url}")

    def save_all_urls(self):
        """为所有网址添加空格◈◈"""
        for i in range(self.url_listbox.size()):
            url = self.url_listbox.get(i)
            if " ◈◈" not in url:
                self.url_listbox.delete(i)
                self.url_listbox.insert(i, url + " ◈◈")
                
        self.save_urls()
        self.log("已全部保存")

    def unsave_all_urls(self):
        """移除所有网址后的空格◈◈"""
        for i in range(self.url_listbox.size()):
            url = self.url_listbox.get(i)
            if " ◈◈" in url:
                self.url_listbox.delete(i)
                self.url_listbox.insert(i, url.replace(" ◈◈", ""))
                
        self.save_urls()
        self.log("已全部取消保存")

    def import_txt(self):
        """导入TXT文件"""
        path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
        if not path:
            return
            
        try:
            with open(path, "r", encoding="utf-8") as f:
                urls = [line.strip() for line in f if line.strip()]
                
            self.url_listbox.delete(0, tk.END)
            for url in urls:
                self.url_listbox.insert(tk.END, url)
                
            self.save_urls()
            self.log(f"已导入 {len(urls)} 条链接")
        except Exception as e:
            self.log(f"导入失败: {str(e)}")

    def toggle_download(self):
        """开始/停止下载"""
        if self.is_running:
            self.is_running = False
            self.start_button.config(text="开始下载")
            self.log("下载已停止")
        else:
            if not self.url_listbox.size():
                messagebox.showwarning("警告", "没有可下载的链接")
                return
                
            self.is_running = True
            self.start_button.config(text="停止下载")
            Thread(target=self.download_urls).start()

    def download_urls(self):
        """逐条下载链接"""
        for i in range(self.url_listbox.size()):
            if not self.is_running:
                break
                
            url = self.url_listbox.get(i).replace(" ◈◈", "")
            self.log(f"开始下载: {url}")
            
            site = self.get_site(url)
            self.log(f"识别平台: {site}")
            self.handle_platform_download(url, site)

        self.is_running = False
        self.root.after(0, lambda: self.start_button.config(text="开始下载"))

    def get_site(self, url: str):
        """根据链接判断所属平台"""
        if "douyin.com" in url:
            return "douyin"
        if "bilibili.com" in url:
            return "bilibili"
        if "youtube.com" in url or "youtu.be" in url:
            return "youtube"
        return "generic"

    def handle_platform_download(self, url: str, site: str):
        """下载分发逻辑"""
        if site == "douyin":
            self.log(">>> 检测到抖音链接，使用专用解析器下载")
            result = handle_aweme_download(url)
            
            if isinstance(result, tuple) and len(result) == 2:
                video_path, audio_path = result
                self.log(f">>> 视频下载完成: {os.path.basename(video_path)}")
                self.log(f">>> 音频下载完成: {os.path.basename(audio_path)}")
                
                # 合成视频和音频
                output_path = os.path.join(
                    os.path.dirname(video_path),
                    f"hc_{os.path.basename(video_path)}"
                )
                
                self.log(f">>> 正在合成视频和音频: {os.path.basename(output_path)}")
                
                try:
                    # FFmpeg合成命令
                    cmd = [
                        'ffmpeg',
                        '-y',  # 覆盖现有文件
                        '-i', video_path,
                        '-i', audio_path,
                        '-c:v', 'copy',  # 复制视频流
                        '-c:a', 'aac',   # 编码为AAC音频
                        '-strict', 'experimental',
                        output_path
                    ]
                    
                    # 执行命令
                    subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                    
                    # 验证输出文件
                    if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                        os.remove(video_path)
                        os.remove(audio_path)
                        self.log(f">>> 合成成功: {os.path.basename(output_path)}")
                        self.log(f">>> 已删除临时文件")
                    else:
                        self.log(">>> 合成失败: 输出文件无效")
                except subprocess.CalledProcessError as e:
                    self.log(f">>> 合成失败: {e.stderr.decode('utf-8')[:500]}")
                except Exception as e:
                    self.log(f">>> 合成失败: {str(e)}")
            else:
                self.log(">>> 下载失败: 无法获取视频或音频路径")
            return

        # 其他平台处理
        base_dir = os.path.join("downloads", site)
        os.makedirs(base_dir, exist_ok=True)

        opts = {
            'quiet': False,
            'outtmpl': os.path.join(base_dir, '%(title)s.%(ext)s'),
        }

        # 下载视频
        self.log(f">>> 从 [{site}] 下载视频…")
        with yt_dlp.YoutubeDL({**opts, 'format': 'bv*'}) as ydl:
            info = ydl.extract_info(url, download=True)
            if info:
                self.log(f">>> 视频下载完成: {info.get('title', '未知名称')}.mp4")

        # 下载音频
        self.log(f">>> 从 [{site}] 下载音频…")
        with yt_dlp.YoutubeDL({**opts, 'format': 'ba'}) as ydl:
            info = ydl.extract_info(url, download=True)
            if info:
                self.log(f">>> 音频下载完成: {info.get('title', '未知名称')}.mp3")

    def open_download_folder(self):
        """打开下载文件夹"""
        folder_path = os.path.join("downloads", "douyin")
        os.makedirs(folder_path, exist_ok=True)
        os.startfile(folder_path)
        self.log(f"已打开文件夹: {folder_path}")

    def load_urls(self):
        """从文件加载网址列表"""
        file_path = os.path.join("sr", "1.txt")
        if not os.path.exists(file_path):
            return
            
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                urls = [line.strip() for line in f if line.strip()]
                
            for url in urls:
                self.url_listbox.insert(tk.END, url.replace(" ◈◈", ""))
                
            self.log(f"已加载 {len(urls)} 条链接")
        except Exception as e:
            self.log(f"加载链接失败: {str(e)}")

    def save_urls(self):
        """保存网址列表到文件"""
        os.makedirs("sr", exist_ok=True)
        file_path = os.path.join("sr", "1.txt")
        
        with open(file_path, "w", encoding="utf-8") as f:
            for i in range(self.url_listbox.size()):
                url = self.url_listbox.get(i)
                if " ◈◈" in url:
                    f.write(url + "\n")
                else:
                    f.write(url + "\n")

    def log(self, message: str):
        """记录日志到终端"""
        self.terminal.configure(state='normal')
        self.terminal.insert(tk.END, message + "\n")
        self.terminal.see(tk.END)
        self.terminal.configure(state='disabled')







    def on_close(self):
        """关闭窗口时清理未保存的链接"""
        self.save_urls()
        self.root.destroy()

def main():
    root = tk.Tk()
    app = VideoDownloaderApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()